/**
 * 
 */
package com.liusoft.android.fmagic;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.media.MediaPlayer;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import static com.liusoft.android.fmagic.BitmapUtils.*;

/**
 * 游戏屏幕
 * @author Winter Lau
 */
public class MagicScreen extends View implements MagicController {

    private MagicSizer sizer;   //游戏大小
	private MagicArray m_array;	//游戏数据
	private GameState m_state;	//游戏状态机
	
	private Bitmap[] cells;		//游戏方块
	private Bitmap background;	//游戏背景
	private Bitmap foreground;	//游戏图片
	
	private boolean audio_on;
	private boolean use_left_hand;
    
    private MediaPlayer mPlayer ;
    private OnFinishListener mFinishListener;
	
	/* 构造函数 */
	public MagicScreen(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }
	public MagicScreen(Context context, AttributeSet attrs) { super(context, attrs); }
	public MagicScreen(Context context) { super(context); }
	
	public void MC_SetOnFinishListener(OnFinishListener listener) {
		this.mFinishListener = listener;
	}
	
	/*************** MagicController 中的方法实现 ******************/
	
	@Override
	public void MC_Init(MagicSizer sizer, Bitmap bg, Bitmap img, boolean audioOn, boolean use_left_hand, String init_game_data) {

		this.MC_SetAudioOn(audioOn);
		this.MC_SetLeftHand(use_left_hand);
		
		this.MC_SetSizer(sizer);
		this.MC_SetBackground(bg);
		this.MC_SetForeground(img);
		
		this.mPlayer = MediaPlayer.create(getContext(), R.raw.teda);
		this.mPlayer.setLooping(false);	
		
		this.m_array = new MagicArray(sizer.getRowCount(), sizer.getColCount());		
		
		this.m_state = new GameState();
		
		this._RestoreGameState(init_game_data);
	}

	/**
	 * 恢复之前的游戏状态
	 * @param array
	 */
	private void _RestoreGameState(String array) {
		if(array!=null)
		try{
			List<Byte> cells = new ArrayList<Byte>();
			StringTokenizer st = new StringTokenizer(array,",");
			while(st.hasMoreTokens()){
				String scell = st.nextToken();
				if(scell.length()>0)
					cells.add(Byte.parseByte(scell));
			}
			m_array.Reset(cells.toArray(new Byte[cells.size()]));
			m_state.Begin();
			m_state.Pause();
			this.invalidate();
		}catch(Exception e){
			Log.e(getClass().getName(), "RestoreGameState", e);
		}
	}

	@Override
	public int MC_GetTimeConsuming() {
		return 0;
	}
	
	@Override
	public String MC_GetGameArray() {
		if(this.m_state.IsRunning() || this.m_state.IsPause()){
			byte[] cells = m_array.GetCurrentCellData();
			StringBuilder sb = new StringBuilder();
			for(byte cell : cells) {
				sb.append(cell);
				sb.append(',');
			}
			return sb.toString();
		}
		return null;
	}

	@Override
	public void MC_SetAudioOn(boolean audioOn) {
		this.audio_on = audioOn;
	}

	@Override
	public void MC_SetLeftHand(boolean use_left_hand) {
		if(this.use_left_hand != use_left_hand){
			this.use_left_hand = use_left_hand;
			if(this.foreground != null)
				this._RefreshForeground();
		}
	}
	
	@Override
	public void MC_SetBackground(Bitmap bmpBg) {
		this.background = bmpBg;
	}
	
	@Override
	public void MC_SetForeground(Bitmap bmpFg) {
		if(bmpFg != this.foreground){			
			this.foreground = bmpFg;
			this._RefreshForeground();
		}
	}
	
	private void _RefreshForeground() {
		Matrix matrix = new Matrix();
		matrix.setRotate(this.use_left_hand?-90:90);	
		
		int[] cell_size = sizer.GetPieceSize();
		int cell_count = sizer.getRowCount() * sizer.getColCount() - 1;
		this.cells = new Bitmap[cell_count];
		
		for(int i=0;i<cell_count;i++){
			int x = (i % sizer.getColCount()) * cell_size[0];
			int y = (i / sizer.getColCount()) * cell_size[1];
			this.cells[i] = MakeGamePiece(Bitmap.createBitmap(this.foreground, x, y, cell_size[0], cell_size[1], matrix, true));
		}			
		this.invalidate();
	}

	@Override
	public void MC_SetSizer(MagicSizer sizer) {
		this.sizer = sizer;
	}

	@Override
	public boolean MC_IsRunning() {
		return this.m_state.IsRunning();
	}
	
	@Override
	public boolean MC_IsPause() {
		return this.m_state.IsPause();
	}
	
	@Override
	public synchronized boolean MC_Start() {
		if(!this.m_state.Begin())
			return false;
		this.m_array.Reset(null);
		this.m_array.Confuse(GameGlobal.COMPLEX_DEGREE);
		this.invalidate();
		return true;
	}

	@Override
	public synchronized boolean MC_Pause() {
		return this.m_state.Pause();
	}
		
	@Override
	public synchronized boolean MC_Redraw() {
		//TODO: 重新计算大小
		this.invalidate();
		return true;
	}
	
	@Override
	public synchronized boolean MC_Reset() {
		if(!this.m_state.Reset())
			return false;
		this.invalidate();
		return true;
	}
	
	/**
	 * 绘制游戏图像
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		Rect board_rect = sizer.GetBoardRect();
		//画边框
		canvas.drawBitmap(background, board_rect.left, board_rect.top, null);
		
		Rect img_rect = sizer.GetImageRect();
		int[] cell_size = sizer.GetPieceSize();
		MagicArray array = m_array;		
		int base_left = board_rect.left + img_rect.left;
		int base_top = board_rect.top + img_rect.top;

		int rowc = sizer.getRowCount();
		int colc = sizer.getColCount();
		//画方块
		for(int row=1;row<=rowc;row++){
			for(int col=1;col<=colc;col++){
				int[] new_cell = _TransferCell(row,col);
				//LogUtils.debug("OnDraw", "%d,%d --> %d,%d", row,col,new_cell[0],new_cell[1]);
				int idx = array.GetCell(new_cell[0], new_cell[1])-1;
				if(idx < 0)
					continue ;
				int left = base_left + (col - 1) * cell_size[0];
				int top = base_top + (row - 1) * cell_size[1];
				canvas.drawBitmap(cells[idx], left, top, null);
			}
		}
	}

	private int[] m_last_cell = {0,0};
	/**
	 * 屏幕滑动事件处理，处理方块移动
	 */
	@Override
	public boolean onTouchEvent(MotionEvent e) {
		
		if(this.m_state.IsReady() && e.getAction() == MotionEvent.ACTION_DOWN) {
			Toast.makeText(getContext(), R.string.begin_msg, Toast.LENGTH_SHORT).show();
			return false ;
		}		
		
		float x = e.getX();  
		float y = e.getY(); 
		
		switch(e.getAction()){  
			case MotionEvent.ACTION_DOWN: 
				this.m_last_cell = _GetCell((int)x, (int)y);
				break;  
			case MotionEvent.ACTION_MOVE:
				break;  
			case MotionEvent.ACTION_UP: 
				int[] move_to_cell = _GetCell((int)x, (int)y);
				if(m_last_cell!=null && move_to_cell != null){
					int[] new_cell = m_array.GetMovableCell(m_last_cell[0], m_last_cell[1]);
					if(new_cell!=null)
					if(new_cell!=null && new_cell[0]==move_to_cell[0] && new_cell[1]==move_to_cell[1]){
						
						if(this.m_state.IsPause())
							this.m_state.Begin();
						
						m_array.Move(m_last_cell[0], m_last_cell[1]);
						this.invalidate();
						//判断是否播放音效
						if(this.audio_on)
							this.mPlayer.start();
						//检查是否游戏结束
						if(m_array.Finish() && this.mFinishListener!=null){
							this.m_state.Finish();
							this.mFinishListener.OnFinish(-1);
						}
					}
				}
				break;
			default:
				return false;
		}  
		return true;  
	}
	
	/**
	 * 返回坐标对应的单元格
	 * @param x
	 * @param y
	 * @return
	 */
	private int[] _GetCell(int x, int y) {
		int[] cell_size = sizer.GetPieceSize();
		Rect img_rect = sizer.GetImageRect();
		Rect board_rect = sizer.GetBoardRect();
		
		int col = ( x - img_rect.left - board_rect.left ) / cell_size[0] + 1;
		int row = ( y - img_rect.top ) / cell_size[1] + 1;
		
		return (m_array.GetCell(row, col)<0)?null:_TransferCell(row,col);
	}

	/**
	 * 矩阵旋转
	 * @param x
	 * @param y
	 * @return
	 */
	private int[] _TransferCell(int x, int y) {
		int RC = sizer.getColCount() + 1;
		return this.use_left_hand?new int[]{y,RC-x}:new int[]{RC-y,x};
	}

}
